<?php
class dbase{
	var $conn, $type, $path, $vurl;
	
	function open(){
		if(!$this->conn){
			$vurl = parse_url($this->vurl);
			$this->type = $vurl['scheme'];
			if($this->type == 'sqlite'){
				if(function_exists('sqlite_open')){
					$this->conn = sqlite_open($vurl['host'] . $vurl['path'], 0666, $error) or die('SQLite Connect Error!');
				}else exit('Cannot find sqlite functions!');
			}else{
				if(isset($vurl['port'])) $vurl['host'] .= ':'. $vurl['port'];
				$this->conn = mysql_connect($vurl['host'], $vurl['user'], $vurl['pass']) or die('MySQL Connect Error!');
    			mysql_select_db(substr($vurl['path'], 1), $this->conn);
				mysql_query('set names utf8;');
				mysql_query('set time_zone = \'+8:00\'');
			}
		}
	}
	
	function close(){
		if($this->conn){
			if($this->type == 'sqlite'){
				@sqlite_close($this->conn);
			}else{
				@mysql_close($this->conn);
			}
		}
	}

	function dbname(){
		$vurl = parse_url($this->vurl);
		$this->type = $vurl['scheme'];
		if($this->type == 'sqlite'){
			return $vurl['host'] . $vurl['path'];
		}elseif($this->type == 'mysql'){
			return substr($vurl['path'], 1);
		}
		return false;
	}
	
	function query($sql){
		$this->open();
		$sql = $this->query_sql($sql);
		if($this->type == 'sqlite'){
			return sqlite_query($this->conn, $sql);
		}else{
			return mysql_query($sql);
		}
	}
	
	// extend
	function query_one($sql, $buf=true){
		$one = false;
		$sql = $this->query_sql($sql);
		if($buf && $this->cache_sql($sql)){
			return $this->cache_get($sql);
		}elseif($res = $this->query($sql)){
			if($row = $this->fetch_array($res)){
				$one = $row[0];
			}
			$this->free_result($res);
		}
		if($buf) $this->cache_set($sql, $one);
		return $one;
	}
	
	function query_row($sql, $buf=true){
		$row = false;
		$sql = $this->query_sql($sql);
		if($buf && $this->cache_sql($sql)){
			return $this->cache_get($sql);
		}elseif($res = $this->query($sql)){
			$row = $this->fetch_assoc($res);
			$this->free_result($res);
		}
		if($buf) $this->cache_set($sql, $row);
		return $row;
	}
	
	function query_all($sql, $buf=true){
		$all = array();
		$sql = $this->query_sql($sql);
		if($buf && $this->cache_sql($sql)){
			return $this->cache_get($sql);
		}elseif($res = $this->query($sql)){
			while($row = $this->fetch_assoc($res)){
				$all[] = $row;
			}
			$this->free_result($res);
		}
		if($buf) $this->cache_set($sql, $all);
		return $all;
	}
	
	function query_str($sql, $buf=true){
		$str = array();
		$sql = $this->query_sql($sql);
		if($buf && $this->cache_sql($sql)){
			return implode(',', $this->cache_get($sql));
		}elseif($res = $this->query($sql)){
			while($row = $this->fetch_assoc($res)){
				$str[] = implode(',', $row);
			}
			$this->free_result($res);
		}
		if($buf) $this->cache_set($sql, $str);
		return implode(',', $str);
	}
	
	function query_list($sql, $page=1, $psiz=20, $buf=true){
		$sql = $this->query_sql($sql);
		$size = $this->query_one(preg_replace('/select(.+?)from/i', 'select count(*) from', $sql, 1), $buf);
			
		$page = intval($page);
		$psiz = intval($psiz);
			
		if($psiz==0) $psiz = 20;
		$pcnt = ceil($size / $psiz);
		if($page>$pcnt){ $page = $pcnt; } 
		if($page<1){ $page = 1; }
		$sql .= ' limit '.(($page-1) * $psiz).','.$psiz;
			
		$list = array();
		$list['data'] = $this->query_all($sql, $buf);
		$list['size'] = $size;
		$list['psiz'] = $psiz;
		$list['pcnt'] = $pcnt;
		$list['page'] = $page;
		$list['psta'] = $page-5>0 ? $page-5 : 1;
		$list['pend'] = $page+5<$pcnt ? $page+5 : $pcnt;
	
		return $list;
	}

	function query_sql($sql){
		if(is_string($sql)){
			return $sql;
		}elseif(is_array($sql)){
			$_sql = '';
			foreach($sql as $key => $val){
				if(is_array($val)){
					$val = implode(', ', $val);
					if(strtolower($key) == 'values'){
						$val = '('. $val .')';
					}
				}
				$_sql .= $key.' '.$val.' ';
			}
			return $_sql;
		}
	}


	// caching
	function cache_sql($sql){
		return is_file($this->path . md5($sql) .'.cache');
	}
	
	function cache_get($sql){
		if(strtolower(substr($sql, 0, 6)) == 'select'){
			$fn = $this->path . md5($sql) .'.cache';
			if($fd = @file_get_contents($fn)){
				return unserialize($fd);
			}
		}
		return false;
	}
	
	function cache_set($sql, $res){
		if(strtolower(substr($sql, 0, 6)) == 'select'){
			$fn = $this->path . md5($sql) .'.cache';
			@file_put_contents($fn, serialize($res));
			
			$db = array();
			$fn = $this->path . md5($this->vurl) .'.cache';
			if($fd = @file_get_contents($fn)){
				$db = unserialize($fd);
			}
	
			foreach($this->cache_tbl($sql) as $tbl){
				if(!array_key_exists($tbl, $db)){
					$db[$tbl] = array();
				}
				if(!in_array(md5($sql), $db[$tbl])){
					$db[$tbl][] = md5($sql);
				}
			}
			@file_put_contents($fn, serialize($db));
			return true;
		}
		return false;
	}
	
	function cache_del($tbl){
		$db = array();
		$fn = $this->path . md5($this->vurl) .'.cache';
		if($fd = @file_get_contents($fn)){
			$db = unserialize($fd);
		}
		if(array_key_exists($tbl, $db)){
			foreach($db[$tbl] as $file){
				@unlink($this->path .$file .'.cache');
			}
			unset($db[$tbl]);
			@file_put_contents($fn, serialize($db));
			return true;
		}
		return false;
	}
	
	function cache_tbl($sql){
		if(strtolower(substr($sql,0,6))=='select'){
			$sql = preg_replace('/[`\t\r\n]+/', ' ', $sql);
			$sql = preg_replace('/select(.+?)from/i', '', $sql, 1);
			$sql = substr($sql, 0, strpos(strtolower($sql .' where '), ' where '));
			
			$tbl = explode(',', $sql);
			foreach($tbl as $key => $val){
				$tbl[$key] = trim($val);
			}
			return $tbl;
		}
		return false;
	}

	// compatible
	function fetch_array($res){
		if($this->type == 'sqlite'){
			return sqlite_fetch_array($res);
		}else{
			return mysql_fetch_array($res);
		}
	}
	
	function fetch_assoc($res){
		if($this->type == 'sqlite'){
			return sqlite_fetch_array($res, SQLITE_ASSOC);
		}else{
			return mysql_fetch_assoc($res);
		}
	}
	
	function free_result($res){
		if($this->type != 'sqlite'){
			return mysql_free_result($res);
		}
	}

	// safe check
	function check(){
		foreach($_GET as $key => $val){ 
			if(is_numeric($val)){ 
				$_GET[$key] = intval($val); 
			}else{ 
				$_GET[$key] = $this->escape($val); 
			}
		} 
		foreach($_POST as $key => $val){ 
			if(is_numeric($val)){ 
				$_POST[$key] = intval($val); 
			}else{ 
				$_POST[$key] = $this->escape($val); 
			}
		}
	}

	function escape($str){
		if(is_array($str)){
			foreach($str as $key => $val)
				$str[$key] = $this->escape($val);
		}elseif(get_magic_quotes_gpc()){
			$str = stripslashes($str);
		}
		return str_replace('\'','\'\'', trim($str));
	}

	function initiate(){
		defined('ROOTDIR') or die('Undefined ROOTDIR!');
		defined('DB_VURL') or die('Undefined DB_VURL!');
	}

	function __construct(){
		$this->initiate();
		$this->conn = null;
		$this->type = 'mysql';
		$this->vurl = DB_VURL;
		$this->path = ROOTDIR .'/caches/data/';
		if(!is_dir($this->path)) mkdir($this->path);
		$this->check();
	}
	
	function __destruct(){
		if($this->conn) $this->close();
	}
}
?>